package com.dq.service.goods.impl;

import com.dq.controller.in.goods.stock.OrgStockCheckQuery;
import com.dq.domain.base.impl.BaseDaoImpl;
import com.dq.domain.category.Category;
import com.dq.domain.goods.centre.OrgGoodsCentre;
import com.dq.domain.org.Org;
import com.dq.domain.sys.user.user.BossUser;
import com.dq.exception.customException.AdminException;
import com.dq.controller.in.goods.stock.StockChangeRecordQuery;
import com.dq.controller.in.base.BaseAdminQuery;

import com.dq.domain.goods.Goods;
import com.dq.domain.goods.Product;
import com.dq.domain.orders.info.OrderInfo;
import com.dq.domain.goods.stock.StockChangeRecord;
import com.dq.domain.sys.section.SysSection;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.repository.BaseRepositories;
import com.dq.service.category.CategoryService;
import com.dq.service.goods.StockChangeRecordService;
import com.dq.service.org.OrgService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.rmi.runtime.Log;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author cf
 */
@Service
@Slf4j
public class StockChangeRecordServiceImpl extends BaseRepositories implements StockChangeRecordService {
    @Autowired
    private OrgService orgService;
    @Autowired
    private CategoryService categoryService;

    /**
     * 不传门店ID参数, 默认获取登录账号门店
     */
    @Override
    public List<StockChangeRecord> list(StockChangeRecordQuery stockChangeRecordQuery) throws AdminException {
        stockChangeRecordQuery.format();
        List<StockChangeRecord> stockChangeRecordLists = new ArrayList<>();
        Long orgId=stockChangeRecordQuery.getOrgId();
        //测试用
        //orgId=0L;
        log.info("stockChangeRecordQuery.getOrgId()="+stockChangeRecordQuery.getOrgId());
        if (orgId == 0) {
            //获取用户管理下的所有门店的信息
            List<Org> listAllByUser = orgService.getListAllByUser();
            for (Org org : listAllByUser) {
                stockChangeRecordQuery.setOrgId(org.getId());
                //构建query
                Map<String, Object> query = createQuery(stockChangeRecordQuery);
                //查询门店库存变动列表
                List<StockChangeRecord> stockChangeRecordList = dao.find(dao.query2Hql(StockChangeRecord.class, query), query);
                //将得到的列表加入到stockChangeRecordLists
                stockChangeRecordLists.addAll(stockChangeRecordList);
            }
            //返回stockChangeRecordLists
            return stockChangeRecordLists;
        }
        Map<String, Object> query = createQuery(stockChangeRecordQuery);

        return dao.find(dao.query2Hql(StockChangeRecord.class, query), query);
    }

    @Override
    public Long count(StockChangeRecordQuery stockChangeRecordQuery) throws AdminException {
        Map<String, Object> query = createQuery(stockChangeRecordQuery);

        return dao.count(dao.count2Hql(StockChangeRecord.class, query), query);
    }

    public Map<String, Object> createQuery(StockChangeRecordQuery stockChangeRecordQuery) {
        Map<String, Object> query = stockChangeRecordQuery.parseMap();

        // 关联门店
        long orgId = stockChangeRecordQuery.getOrgId() == null ? sysUserService.getUserInSection().getSection().getId() : stockChangeRecordQuery.getOrgId();
        query.put("org_id", orgId);
        query.remove("orgId");

        if (StringUtils.isNotEmpty(stockChangeRecordQuery.getGoodsName())) {
            query.put("goods_goodsName" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(stockChangeRecordQuery.getGoodsName()));
            query.remove("goodsName");
        }
        if (StringUtils.isNotEmpty(stockChangeRecordQuery.getGoodsNo())) {
            query.put("goods_goodsNo" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(stockChangeRecordQuery.getGoodsNo()));
            query.remove("goodsNo");
        }
        if (stockChangeRecordQuery.getCategoryId() != null) {
            List<Category> categoryList = categoryService.getParCategory(stockChangeRecordQuery.getCategoryId());
            List<Long> idsInList = new ArrayList<>();
            idsInList.add(stockChangeRecordQuery.getCategoryId());
            for (Category category : categoryList) {
                idsInList.add(category.getId());
            }
            query.put("goods_category_id" + BaseDaoImpl.inSqlStr, idsInList);
            query.remove("categoryId");
        }
        if (stockChangeRecordQuery.getUpdateUserId() != null) {
            query.put("updateUser_id", stockChangeRecordQuery.getUpdateUserId());
            query.remove("updateUserId");
        }
        if (stockChangeRecordQuery.getTimeBegin() != null) {
            query.put("lastModifyTime" + BaseDaoImpl.gteSqlStr, stockChangeRecordQuery.getTimeBegin());
            query.remove("timeBegin");
        }
        if (stockChangeRecordQuery.getTimeEnd() != null) {
            query.put("lastModifyTime" + BaseDaoImpl.lteSqlStr, stockChangeRecordQuery.getTimeEnd());
            query.remove("timeEnd");
        }

        return query;
    }

    @Override
    public List<StockChangeRecord> listGroupByGoodsAndOrg(StockChangeRecordQuery stockChangeRecordQuery) throws AdminException {
        stockChangeRecordQuery.format();
        Map<String, Object> query = createQuery(stockChangeRecordQuery);
        query.put(BaseDaoImpl.HQL_GROUP, "u.goods.id, u.org.id");

        return dao.find(dao.query2Hql(StockChangeRecord.class, query), query);
    }

    @Override
    public Long countGroupByGoodsAndOrg(StockChangeRecordQuery stockChangeRecordQuery) throws AdminException {
        Map<String, Object> query = createQuery(stockChangeRecordQuery);
        query.put(BaseDaoImpl.HQL_GROUP, "u.goods.id, u.org.id");

        return dao.count(dao.count2Hql(StockChangeRecord.class, query), query);
    }


    /**
     * 根据子订单信息, 生成 库存变更记录, 修改对应商品product库存
     * 调用 saveStockChangeRecord()
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void orderInfo2Stock(SysSection org, OrderInfo orderInfo, StockChangeRecord.ChangeDirection changeDirection,
                                StockChangeRecord.ChangeType changeType) throws AdminException {
        Goods goods = orderInfo.getGoods();
        Product product = orderInfo.getProduct();
        if (goods == null || product == null) {
            throw new AdminException("商品信息获取异常");
        }
        StockChangeRecord stockChangeRecord = new StockChangeRecord();
        stockChangeRecord.setChangeDirection(changeDirection);
        stockChangeRecord.setChangeType(changeType);

        stockChangeRecord.setNum(orderInfo.getNumber());
        stockChangeRecord.setRemarks("orderInfo 对应库存变动记录");

        //  添加 库存变动, 细化到product, 同时修改对应商品库存
        saveStockChangeRecord(stockChangeRecord, goods, product, org, true);
    }

    /**
     * 添加 库存变动, 只选择goods, 默认product
     * 调用 saveStockChangeRecord()
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public StockChangeRecord addStockChangeRecord(StockChangeRecord stockChangeRecord) throws AdminException {
        if (stockChangeRecord.getGoodsId() == null) {
            throw new AdminException("goodsId参数异常");
        }
        Goods goods = dao.get(Goods.class, stockChangeRecord.getGoodsId());
        if (goods == null) {
            throw new AdminException(String.format("%s 无对应商品信息", stockChangeRecord.getGoodsId()));
        }
        // 获取goods默认product 添加库存变动记录
        Product product = productRepository.findByGoodsAndDeletedFalseAndIsDefaultTrue(goods);
        if (product == null) {
            throw new AdminException(String.format("goodsId:%s 无对应默认product信息", stockChangeRecord.getGoodsId()));
        }

        // 关联门店
        SysSection section;
        if (stockChangeRecord.getOrgId() == null) {
            section = sysUserService.getUserInSection().getSection();
        } else {
            section = dao.get(SysSection.class, stockChangeRecord.getOrgId());
            if (section == null) {
                throw new AdminException(String.format("%s 无对应门店信息", stockChangeRecord.getOrgId()));
            }
        }
        if (stockChangeRecord.getSellUserId() != null) {
            BossUser sellUser = dao.get(BossUser.class, stockChangeRecord.getSellUserId());
            if (sellUser == null) {
                throw new AdminException("所选售出员工不存在");
            }
            stockChangeRecord.setSellUser(sellUser);
        }

        // 添加 库存变动, 细化到product, 同时修改对应商品库存
        stockChangeRecord = saveStockChangeRecord(stockChangeRecord, goods, product, section, true);

        return stockChangeRecord;
    }

    /**
     * 添加 库存变动, 细化到product
     * 同时修改对应商品product库存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public StockChangeRecord saveStockChangeRecord(StockChangeRecord stockChangeRecord, Goods goods, Product product, SysSection section, boolean judge) throws AdminException {
        if (null == goods || product == null) {
            throw new AdminException("商品/product 信息异常");
        }
        if (section == null) {
            throw new AdminException("门店 信息异常");
        }

        stockChangeRecord.setOrg(section);
        stockChangeRecord.setGoods(goods);
        stockChangeRecord.setProduct(product);

        // 初始化库存变动记录
        stockChangeRecord = initObject(stockChangeRecord);

        if (null == stockChangeRecord.getNum()) {
            throw new AdminException("库存变动数量为空");
        }

        if (stockChangeRecord.getChangeDirection() == null) {
            throw new AdminException("商品变动方向异常");
        }
        // TODO 变动方向为ADD, 变动类型为空时, 默认设为 adjust
        if (stockChangeRecord.getChangeType() == null) {
            if (stockChangeRecord.getChangeDirection().toString().equals(StockChangeRecord.ChangeDirection.add.toString())) {
                stockChangeRecord.setChangeType(StockChangeRecord.ChangeType.adjust);
            } else {
                throw new AdminException("商品变动类型异常");
            }
        }
        if (stockChangeRecord.getChangeDirection().toString().equals(StockChangeRecord.ChangeDirection.reduce.toString())) {
            if (stockChangeRecord.getChangeType().toString().equals(StockChangeRecord.ChangeType.sell.toString())) {
                // 出库-出售, 价格限制
                if (stockChangeRecord.getReducePrice().compareTo(stockChangeRecord.getGoods().getPrice()) < 0) {
                    throw new AdminException("出库价格小于最低价");
                }
                if (stockChangeRecord.getSellUser() == null) {
                    throw new AdminException("售出员工为空");
                }
            }
        }
        if (stockChangeRecord.getStockStatus() == null) {
            throw new AdminException("库存变动记录审核状态异常");
        }

        if (judge) {
            // 002: 加载门店商品关联对象
            OrgGoodsCentre orgGoodsCentre = orgGoodsCentreRepository.findByOrgAndProductAndDeletedFalse(section, product);
            if (orgGoodsCentre == null || orgGoodsCentre.getId() == null) {
                orgGoodsCentre = new OrgGoodsCentre();
                orgGoodsCentre.setOrg(section);
                orgGoodsCentre.setGoods(goods);
                orgGoodsCentre.setProduct(product);
                if (stockChangeRecord.getChangeDirection().toString().equals(StockChangeRecord.ChangeDirection.add.toString())) {
                    orgGoodsCentre.setCount(stockChangeRecord.getNum());
                } else {
                    throw new AdminException("门店还无此商品, 不能减库存");
                }
                orgGoodsCentre = orgGoodsCentreService.initObject(orgGoodsCentre);
            } else {
                if (stockChangeRecord.getChangeDirection().toString().equals(StockChangeRecord.ChangeDirection.add.toString())) {
                    orgGoodsCentre.setCount(orgGoodsCentre.getCount() + stockChangeRecord.getNum());
                } else {
                    if ((orgGoodsCentre.getCount() - stockChangeRecord.getNum()) < 0) {
                        throw new AdminException("门店此商品库存不足");
                    }
                    orgGoodsCentre.setCount(orgGoodsCentre.getCount() - stockChangeRecord.getNum());
                }
            }

            // 001: 保存库存变更记录
            stockChangeRecord.setThenStock(orgGoodsCentre.getCount());
            stockChangeRecord = stockChangeRecordRepository.save(stockChangeRecord);
            // 002: 修改对应商品库存
            orgGoodsCentreRepository.save(orgGoodsCentre);
        }

        return stockChangeRecord;
    }

    /**
     * 删除 库存变动, 细化到product
     * 同时修改对应商品product库存
     */
    @Override
    public void delStockChangeRecord(Long id) throws AdminException {
        SysUser loginUser = sysUserService.getUserInSection();
        StockChangeRecord stockChangeRecord = dao.get(StockChangeRecord.class, id);
        if (null == stockChangeRecord) {
            throw new AdminException("库存变更记录不存在");
        }

        boolean delJudge = false;
        List<Org> orgListByLogin = orgService.getListAllByUser();
        for (Org org : orgListByLogin) {
            if (stockChangeRecord.getOrg().getId().toString().equals(org.getId().toString())) {
                delJudge = true;
                break;
            }
        }
        if (!delJudge) {
            throw new AdminException("记录不属于你管理， 不能删除");
        }

        stockChangeRecord.setDeleted(true);
        stockChangeRecord.setLastModifyTime(System.currentTimeMillis());
        stockChangeRecord.setUpdateUser(loginUser);

        // 002: 加载门店商品关联对象
        OrgGoodsCentre orgGoodsCentre = orgGoodsCentreRepository.findByOrgAndProductAndDeletedFalse(stockChangeRecord.getOrg(), stockChangeRecord.getProduct());
        if (orgGoodsCentre == null) {
            throw new AdminException("数据异常， 库存记录关联商品 丢失");
        }
        if (stockChangeRecord.getChangeDirection().toString().equals(StockChangeRecord.ChangeDirection.add.toString())) {
            /// 判断库存
            if ((orgGoodsCentre.getCount() - stockChangeRecord.getNum()) < 0) {
                throw new AdminException("门店此商品库存不足支持删除记录减去已赠库存， 不能删除");
            }
            orgGoodsCentre.setCount(orgGoodsCentre.getCount() - stockChangeRecord.getNum());
        } else {
            orgGoodsCentre.setCount(orgGoodsCentre.getCount() + stockChangeRecord.getNum());
        }

        // 001: 删除库存记录
        stockChangeRecordRepository.save(stockChangeRecord);
        // 002: 修改对应商品库存
        orgGoodsCentreRepository.save(orgGoodsCentre);
    }

    /**
     * 对象初始化
     */
    @Override
    public StockChangeRecord initObject(StockChangeRecord stockChangeRecord) throws AdminException {
        // todo 库存变更记录不用审批， 默认生成 审批通过
        stockChangeRecord.setStockStatus(StockChangeRecord.StockStatus.ApprovalSuccess);

        SysUser user = sysUserService.getUser();
        stockChangeRecord.setCreateUser(user);
        stockChangeRecord.setUpdateUser(user);

        return stockChangeRecord;
    }

    /**
     * 总库存
     */
    @Override
    public Long orgStockAll(OrgStockCheckQuery orgStockCheckQuery) throws AdminException {
        // 关联门店, 门店ID, 不传默认是登录账号门店下
        Long orgId = orgStockCheckQuery.getOrgId() == null ? sysUserService.getUserInSection().getSection().getId() : orgStockCheckQuery.getOrgId();

        String format = String.format(
                "SELECT IFNULL(SUM(u.num),0) AS countall FROM stock_change_record u " +
                        " WHERE 1=1 " +
                        " AND u.org_id = %s " +
                        " AND u.change_direction = 0 ", orgId
        );

        return countStatSql(format, orgStockCheckQuery).longValue();
    }

    /**
     * 消耗统计
     */
    @Override
    public Long orgExpendAll(OrgStockCheckQuery orgStockCheckQuery) throws AdminException {
        // 关联门店, 门店ID, 不传默认是登录账号门店下
        Long orgId = orgStockCheckQuery.getOrgId() == null ? sysUserService.getUserInSection().getSection().getId() : orgStockCheckQuery.getOrgId();

        String format = String.format(
                "SELECT IFNULL(SUM(u.num),0) AS countall FROM stock_change_record u " +
                        " WHERE 1=1 " +
                        " AND u.org_id = %s " +
                        " AND u.change_direction = 1 " +
                        " AND u.change_type = 0 ", orgId
        );

        return countStatSql(format, orgStockCheckQuery).longValue();
    }

    /**
     * 售出统计
     */
    @Override
    public Long orgSellAll(OrgStockCheckQuery orgStockCheckQuery) throws AdminException {
        // 关联门店, 门店ID, 不传默认是登录账号门店下
        Long orgId = orgStockCheckQuery.getOrgId() == null ? sysUserService.getUserInSection().getSection().getId() : orgStockCheckQuery.getOrgId();

        String format = String.format(
                "SELECT IFNULL(SUM(u.num),0) AS countall FROM stock_change_record u " +
                        " WHERE 1=1 " +
                        " AND u.org_id = %s " +
                        " AND u.change_direction = 1 " +
                        " AND u.change_type = 1 ", orgId
        );

        return countStatSql(format, orgStockCheckQuery).longValue();
    }

    /**
     * 当前库存
     */
    @Override
    public Long orgRealStockAll(OrgStockCheckQuery orgStockCheckQuery) throws AdminException {
        // 关联门店, 门店ID, 不传默认是登录账号门店下
        Long orgId = orgStockCheckQuery.getOrgId() == null ? sysUserService.getUserInSection().getSection().getId() : orgStockCheckQuery.getOrgId();

        String format = String.format(
                "SELECT " +
                        " IFNULL(SUM(CASE WHEN u.change_direction = 0 THEN +u.num ELSE -u.num END),0) AS countall " +
                        " FROM stock_change_record u " +
                        " WHERE 1=1 " +
                        " AND u.org_id = %s ", orgId
        );

        return countStatSql(format, orgStockCheckQuery).longValue();
    }

    /**
     * 售出总额统计
     */
    @Override
    public BigDecimal orgSellPriceAll(OrgStockCheckQuery orgStockCheckQuery) throws AdminException {
        // 关联门店, 门店ID, 不传默认是登录账号门店下
        Long orgId = orgStockCheckQuery.getOrgId() == null ? sysUserService.getUserInSection().getSection().getId() : orgStockCheckQuery.getOrgId();

        String format = String.format(
                "SELECT IFNULL(SUM(u.reduce_price),0) AS countall FROM stock_change_record u\n" +
                        " WHERE 1=1 " +
                        " AND u.org_id = %s " +
                        " AND u.change_direction = 1 " +
                        " AND u.change_type = 1 ", orgId
        );

        return countStatSql(format, orgStockCheckQuery);
    }

    public BigDecimal countStatSql(String format, OrgStockCheckQuery orgStockCheckQuery) throws AdminException {
        StringBuilder sql = new StringBuilder();
        sql.append(format);
        if (orgStockCheckQuery.getBeginTime() != null) {
            sql.append(" and u.create_time >= ").append(orgStockCheckQuery.getBeginTime());
        }
        if (orgStockCheckQuery.getEndTime() != null) {
            sql.append(" and u.create_time <= ").append(orgStockCheckQuery.getEndTime());
        }

        System.out.println(sql.toString());
        List<Map> list = dao.findBySql2Map(sql.toString(), new HashMap<>(16));
        BigDecimal count = new BigDecimal("0");
        if (list != null && list.size() > 0) {
            if (list.size() > 1) {
                throw new AdminException("数据异常");
            }
            Map map = list.get(0);
            count = new BigDecimal(map.get("countall").toString());
        }

        return count;
    }

}
